//
//  LWComposeView.swift
//  LW_Weibo
//
//  Created by 刘伟 on 16/7/16.
//  Copyright © 2016年 LWSpro. All rights reserved.
//

import UIKit
import pop

private let addHeight: CGFloat = 350


class LWComposeView: UIView {
    
//要跳转控制器 只有控制器才能跳转控制器 而且必须是已经加到APP上面的，即 必须是加到keyWindow上的控制器  只要是主窗口上的控制器都能跳转控制器  所以必须要有一个控制器  可以采用闭包 传一个控制器过来 或者传一个控制器过去 让LWMainTabBarCtroller 去跳转  采用闭包有点复杂 下面我们采取属性记录的方法  控制器跳转控制器完毕之后  我们需要把蒙版移除  节省内存

    //属性 记录传过来的控制器  因为LWComposeView是点击LWMainTabBarCtroller的tabbar上面的加号按钮弹出来的  所以我们可以在创建LWComposeView的时候  将LWMainTabBarCtroller 控制器给LWComposeView的一个属性
    //私有属性  我们通过外面调用的show(target: UIViewController)这个方法 将LWMainTabBarCtroller 作为参数传过来  然后我们只需要用这个属性在show(target: UIViewController) 这个方法中去记录一下  这样也就没有将属性暴露在外面 更安全
    private var target: UIViewController?
    
    
    //设置一个数组,存储按钮
    var composeBtnArr: [LWComposeMenuButton] = [LWComposeMenuButton]()
    
    
    
    //MARK: - 懒加载控件  调用第三方框架
    private lazy var bgImageView: UIImageView = UIImageView(image: UIImage.getScreenShot().applyLightEffect())
    
    
    
    //MARK: - 重写
    override init(frame: CGRect) {
        
        super.init(frame: frame)
        
        layoutUI()
        
        
    }
    
    
    
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    
    
    
    //截取屏幕快照 越模糊越好  截取屏幕的照片  也即是需要返回一个UIImage 一般如果一个方法中有返回值 并且返回值是一个控件 那么我们可以抽取出来 写到那个返回值的分类中  截取屏幕的快照抽取到了UIImage的分类中
    
    
    
    //MARK: - 添加控件 设置约束
    func layoutUI() {
        
        backgroundColor = RandomColor()
        
        //设置视图大小
        self.frame.size = CGSize(width: SCreenWidth, height: SCreenHeight)
        
        //添加控件
        addSubview(bgImageView)
        
        //设置约束
        bgImageView.snp_makeConstraints { (make) -> Void in
            
            make.edges.equalTo(self).offset(UIEdgeInsetsZero)
            
        }
        
        
        //添加按钮
        addChildButton()
        
    }
    
    
    
    
    //MARK: - 添加到父控件
    //最终都是要将当前视图添加到父控件上,我们就 直接在当前视图里直接添加即可  前提是能拿到父控件
    func show(target: UIViewController) {
        
        
        //在LWMainTabBarController中调用show这个方法时  我们可以将LWMainTabBarController 作为参数传过来  然后用属性记录一下  因为要拿到控制器去跳转控制器
        
        self.target = target
        
        //  获取最上面的一个window  防止有键盘弹出来的时候 会出现keyWindow获取错误
//        let window = UIApplication.sharedApplication().windows.last!
//        
//        window.addSubview(self)
//        
        //蒙版加到主窗口可以 加到我们传递过来的呃控制器上面也可以 如果 传过来的控制器是导航控制器的话 那么导航栏会盖不住
        target.view.addSubview(self)
        
        
        //调用这个方法  就让按钮以弹簧动画的效果出现在屏幕上（钻出来的）
        
        for (i, value) in composeBtnArr.enumerate() {
            
            
            startAnimation(value, i: i, isUp: true)
            
        }
        
        
        
        
    }
    
    //MARK: - 抽取方法的逻辑
    /*
        这个方法 animationToView()  和 touchesBegan 方法中 都用到了类似的方法  唯一变动的是y  所以我们抽取到  startAnimation()  这个方法中  缺什么我们补什么
    
    
    //以动画的形式让按钮从底部钻出来
    func animationToView() {
    
    let animation = POPSpringAnimation(propertyNamed: kPOPViewCenter)
    
    for (i,value) in composeBtnArr.enumerate() {
    
    //动画要执行的目的地 要从下面钻出来 用 -
    animation.toValue = NSValue(CGPoint: CGPoint(x: value.centerX, y: value.centerY - addHeight))
    
    
    //设置弹簧效果 抖动幅度范围 range [0, 20]
    animation.springBounciness = 8
    
    //抖动的初始速度
    animation.springSpeed = 10
    
    //开始动画时间  随着i的改变 取出来的value也会跟着改变 所以用i 来表示每一个按钮弹出来的时间  相当于后一个按钮比前一个按钮要延迟 0.025秒弹出
    animation.beginTime = CACurrentMediaTime() + Double(i) * 0.025
    
    
    //执行动画
    value.pop_addAnimation(animation, forKey: nil)
    
    
    }
    
    
    
    
    }
    
    

    
    
    */
    
    
    
    
    
    
    
    
    
    
    //MARK: - 以动画的形式从屏幕下面一个个钻出来
    // isUp 这个Bool值 是用来判断 y 的 通过三目运算符来判断
    
    private func startAnimation(value: LWComposeMenuButton, i: Int, isUp: Bool) {
        
        let animation = POPSpringAnimation(propertyNamed: kPOPViewCenter)
        
       //如果是true  那么就是 - (钻出来)   false 就是 +  (回到底部)
        let y = isUp ? value.centerY - addHeight : value.centerY + addHeight
        
            
            //动画要执行的目的地 要从下面钻出来 用 -
            animation.toValue = NSValue(CGPoint: CGPoint(x: value.centerX, y: y))
            
            
            //设置弹簧效果 抖动幅度范围 range [0, 20]
            animation.springBounciness = 8
            
            //抖动的初始速度
            animation.springSpeed = 10
            
            //开始动画时间  随着i的改变 取出来的value也会跟着改变 所以用i 来表示每一个按钮弹出来的时间  相当于后一个按钮比前一个按钮要延迟 0.025秒弹出
            animation.beginTime = CACurrentMediaTime() + Double(i) * 0.025
            
            
            //执行动画
            value.pop_addAnimation(animation, forKey: nil)
        

    
    
    
    }
    
    
    
    
    
    
    //MARK: - 创建button
    private func addChildButton() {
        
        //一行有3个按钮 固定的 是个Int类型
        let rowBtnNums: Int = 3
        
        //把按钮的宽高定死
        let btnW: CGFloat = 80
        let btnH: CGFloat = 110
        
        //间距 屏幕宽度 - 3 * 按钮宽度 / （3 + 1）
        let btnMargin: CGFloat = (width - CGFloat(rowBtnNums) * btnW) / CGFloat(rowBtnNums + 1)
        
        
        //需要根据数组中元素的个数  来确定需要创建多少个按钮
        let btnComposeMenuArray = loadComposePlist()
        
        
        for (i, value) in btnComposeMenuArray.enumerate() {
            
            //创建按钮
            let button = LWComposeMenuButton()
            
            //给button的模型赋值
            button.composeMenu = value
            
            //点击事件 要记录是哪个button  所以有参数
            button.addTarget(self, action: "buttonAction:", forControlEvents: .TouchUpInside)
            
            button.size = CGSize(width: btnW, height: btnH)
            //  计算列的索引
            let colIndex = i % rowBtnNums
            //  计算行的索引
            let rowIndex = i / rowBtnNums
            
            //  计算x坐标
            button.x = btnW * CGFloat(colIndex) + CGFloat(colIndex + 1) * btnMargin
            
            //  计算y坐标  后面加上SCreenHeight 是为了让这些按钮一开始是在下面的  我们点击' + ' 让按钮仿佛是一个个从下面钻出来的
            button.y = btnH * CGFloat(rowIndex) + CGFloat(rowIndex) * btnMargin + SCreenHeight
            
            button.setImage(UIImage(named: value.icon!), forState: .Normal)
            
            button.setTitle(value.title!, forState: .Normal)
            
            addSubview(button)
            
            
            //添加到数组中
            composeBtnArr.append(button)
            
        }
        
        
        
    }
    
    
    // MARK:    - 点击按钮事件
    //点击按钮变大 其他按钮变小
    @objc private func buttonAction(btn: LWComposeMenuButton) {
        
        //以动画的形式
        UIView.animateWithDuration(0.36, animations: { () -> Void in
            
            //遍历按钮数组
            for value in self.composeBtnArr {
                
                //透明度  所有的按钮
                value.alpha = 0.2
                //倍数
                let currentScale: CGFloat = 3
                let otherScale: CGFloat = 0.2
                
                if value == btn { //这个btn就是我们点击的那个按钮
                    
                    value.transform = CGAffineTransformMakeScale(currentScale, currentScale)
                    
                }else { //其他按钮变小
                    
                    value.transform = CGAffineTransformMakeScale(otherScale, otherScale)
                    
                    
                }
                
                
            }
            

            
            
            }) { (_) -> Void in  //动画完毕之后  按钮恢复原有大小
                
                UIView.animateWithDuration(0.36, animations: { () -> Void in
                    
                    
                    for value in self.composeBtnArr {
                        
                        value.alpha = 1
                        //所有按钮恢复原有大小
                        value.transform = CGAffineTransformIdentity
                        
                        
                    }
                    
                    
                }, completion: { (_) -> Void in
                        
                    //完成之后,跳转控制器
                    //强转控制器 swift中用类名转换成类 强转需要加上.Type
                    let classType = NSClassFromString(btn.composeMenu!.className!) as! UIViewController.Type
                    
                    //创建指定对象
                    let vc = classType.init()
                    
                    //创建一个导航控制器  传过来的控制器 并不是导航控制器的根控制器  是LWMainTabBarCtroller  所以我们要跳转  使用presentViewController
                    
                    let nav = UINavigationController(rootViewController: vc)
                    
                    //跳转
                    self.target?.presentViewController(nav, animated: true, completion: { () -> Void in
                        
                        //跳转完毕后 移除蒙版视图
                        self.removeFromSuperview()
                        
                        
                        
                        
                    })

                        
                        
                        
                })
                
                
                
        }
        
        
        
        
    }
    
    
    //MARK: - 加载plist文件
    //将plist文件加载出来数据转换成模型  然后放到数组中 在将数组传回
    func loadComposePlist() -> [LWComposeMenu] {
        
        //先用数组接收 接收到的是字典数组 因为这个plist文件里面存放的是字典数组
        let composeDicArr = NSArray(contentsOfFile: (NSBundle.mainBundle().pathForResource("compose.plist", ofType: nil))!)
        
        //可变数组 用于接收转换成的模型
        var tempArr = [LWComposeMenu]()
        
        
        //遍历这个字典数组  将里面的字典元素转换成模型
        for dic in composeDicArr! {
            
            let compMenu = LWComposeMenu(dic: dic as! [String : AnyObject])
            
            tempArr.append(compMenu)
            
            
        }
        
        
        return tempArr
        
        
    }
    
    
    
    //MARK: - 触摸屏幕
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
        //移除蒙版前  我们让 按钮先一个个回到底部  注意是最后一排的按钮的最后一个按钮先回去,然后是最后一排的倒数第二个按钮再回去,依次下去  所以数组中的元素 应该倒着取值
        
        /*
        
        
        let animation = POPSpringAnimation(propertyNamed: kPOPViewCenter)
        
        for (i,value) in composeBtnArr.reverse().enumerate() {// reverse() 倒着取值
            
            // i首先取得的是0  value首先取得的是数组中最后一个按钮
            
            //动画要执行的目的地 要从上面回去  用 +
            animation.toValue = NSValue(CGPoint: CGPoint(x: value.centerX, y: value.centerY + addHeight))
            
            
            //设置弹簧效果 抖动幅度范围 range [0, 20]
            animation.springBounciness = 8
            
            //抖动的初始速度
            animation.springSpeed = 10
            
            //开始动画时间  随着i的改变 取出来的value也会跟着改变 所以用i 来表示每一个按钮弹出来的时间  相当于后一个按钮比前一个按钮要延迟 0.025秒弹出
            animation.beginTime = CACurrentMediaTime() + Double(i) * 0.025
            
            
            //执行动画
            value.pop_addAnimation(animation, forKey: nil)
            
            
        }

        */
        
        
        for (i,value) in composeBtnArr.reverse().enumerate() {// reverse() 倒着取值
        
        
            startAnimation(value, i: i, isUp: false)
            
        
        }
        //触摸屏幕  从父控件移除
        //我们的蒙版是要从父控件上面移除的  这个方法就是直接从父控件移除 并不用写在父控件中 只要有父控件 那么这个方法就可以执行
        
        //要让这个方法在 上面那个方法后面执行 不然按钮一个个钻回底部的效果就看不到了  因为按钮钻回去的过程是耗时操作
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(0.3 * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), { () -> Void in
            
            //  移除
            self.removeFromSuperview()
            
        })
        
        
        
        
    }
    
    
    
    
    
}

    
    
    
    


